---------------------------------------------------------------
File name   :  vv_ahblite_master_bfm.e
Title       :  The master BFM
Project     :  vv_ahblite eVC
Developers  :  stefan,filip
Created     :  27.07.2011.
Description :  This file adds master functionality to the generic BFM.
Notes       :  
---------------------------------------------------------------
Copyright  (c)2011
---------------------------------------------------------------

<'
package vv_ahblite;

-- ====================================================================
-- The master BFM extends the generic BFM
-- ====================================================================
extend vv_ahblite_master_bfm {
 
    -- This TCM continuously gets transactions from the driver and passes
    -- them to the BFM.
    main_loop() @p_sys_smp.clk is {
    	--start do_mux1(); --####@@@@
    	--start do_mux2(); --####@@@@
    	--start do_mux3(); --####@@@@
    	
    	var transaction_idle : MASTER vv_ahblite_transaction;
    	
    	--last_slave = p_env.slaves[0];
    	while TRUE {
            message(LOW, "MASTER BFM MAIN LOOP START!!!!");
            transaction = p_driver.get_next_item();
            message(LOW, "MASTER BFM GOT NEXT ITEM");
            
            if ( p_env.bus_monitor.transaction.response == 1 and
            		p_env.bus_monitor.transaction.ready == 0 )  
            {
            	
            	gen transaction_idle keeping {
            		.addr == p_env.bus_monitor.transaction.addr;
            		.burst == SINGLE;
            		.lock == 0;
            		.protect == 0x3;
            		.data_size == BYTE;
            		.transfer == IDLE;
            		.write_op == 0;
            --.transaction_kind == MASTER;
            	};
            
            drive_transaction(transaction_idle);
            
            while ( transaction.transfer != NONSEQ )
            	{
            		emit p_driver.item_done;
            		transaction = p_driver.get_next_item();
             	};
                      	
            };	
            
            drive_transaction(transaction);
            
            emit p_driver.item_done;
        }; 
    }; 
    
    
    
    
    
    
    
    
    -- This TCM gets a transaction and drive it into the DUT
    drive_transaction (cur_transaction : vv_ahblite_transaction)
      @p_sys_smp.clk is {
        
        message(LOW, "transaction started: ", cur_transaction.transaction_str());
        cur_transaction.start_transaction();
                  
        message(LOW, "DRIVE transaction CONTROL: ", cur_transaction.transaction_str());
        
        drive_transaction_address(cur_transaction);
        drive_control_signals(cur_transaction);
        --init_values(); 

        wait cycle;

        -- before driving new control signals  if slave agent is not ready (HREADY=0)  wait for it to become ready (HREADY=1) 
        -- the master must not change the transfer type unless
        -- idle or (bysy with defined or undefined burst)
        
        
        if(cur_transaction.transfer != IDLE or 
        !(cur_transaction.transfer == BUSY and cur_transaction.burst == SINGLE))
        {
        
        	sync true (p_smp.h_ready$ == 1 or p_smp.h_resp$ == 1);  --TODO
        }; --@@@@ if we sync at monitor.transaction.ready there is one extra wait state??
        --extending the data phase of the transfer to address X 
        --has the effect of extending the address phase of the transfer to address X+1.
        
        --@@@@ TODO if there is an ERROR response from the slave
        -- when there is an error the ready signal also drops to 0 in the first error cycle.
        -- if there is an error response from the slave the master can cansel the burs by driving the idle tranfer, 
        -- or it van contiue the burst
        
        -- after driving the control signals and address wait for  one cycle and then drive the data 
        if (cur_transaction.write_op == 1) 
        {
            message(LOW, "DRIVE transaction DATA: ", cur_transaction.transaction_str());
            drive_transaction_data(cur_transaction);
        };--@@@@ else we could read the data...
           


        -- ******************************************************************
       
        message(HIGH, "transaction completed: ", cur_transaction.transaction_str());
        cur_transaction.end_transaction();
    };


    
    -- This TCM drives the address of the transaction 
    drive_transaction_address (cur_transaction : vv_ahblite_transaction)
      @p_sys_smp.clk is {
        
        p_smp.h_addr$ = cur_transaction.addr;   
    };
      
    -- This TCM drives the controll signals of the transaction 
    drive_control_signals (cur_transaction : vv_ahblite_transaction)
      @p_sys_smp.clk is {
      	p_smp.h_write$ = cur_transaction.write_op;
        p_smp.drive_h_size(cur_transaction.data_size);
        p_smp.drive_h_burst(cur_transaction.burst)  ;
        p_smp.h_prot$ = cur_transaction.protect  ;
        p_smp.drive_h_trans(cur_transaction.transfer)  ;
        p_smp.h_mastlock$ = cur_transaction.lock  ;
    };
    
    -- This TCM drives the data of the transaction 
    drive_transaction_data (cur_transaction : vv_ahblite_transaction)
      @p_sys_smp.clk is {
      	--p_smp.h_wdata.put_mvl_list(32'hxxxxxxxx);
        --wait delay(5);
        
        --packing a list creates a bit stream by concatenating the list items together
        p_smp.h_wdata$ = pack(packing.low,cur_transaction.write_data);
    };
    
    -- This method initializes the master values.
    init_values() is {
        -- Init the signals       
    	
    	--p_smp.h_resp$ = 0; 
        --p_smp.h_ready$ = 1; 
        --p_smp.h_rdata$ = 0; 
    	
    	
    	p_smp.h_addr$ = 0;
        p_smp.h_write$ = 0  ;
        p_smp.drive_h_size(BYTE)  ;
        p_smp.drive_h_burst(SINGLE)  ;
        p_smp.h_prot$ = 0 ;
        p_smp.drive_h_trans(IDLE)  ;
        p_smp.h_mastlock$ = 0 ;
        p_smp.h_wdata$ = 0;           
        
        
        -- ******************************************************************   
        -- Init the items  
        transaction = NULL;       
    }; 

    -- Run the main master BFM.
    run() is also {
        message(LOW, "The master BFM started");
        init_values();
        start main_loop();
    }; 

}; 



'>
